import {
  isUndefined,
  isNull,
  BackendServices,
  dateFormat,
  randomString,
} from "mmb";
import * as inventorypb from "../grpc-client/proxy/inventory_pb";

import {
  getInventoryProxySafely,
  getMetadata,
  getOptionsOfLight,
  wrapperGrpcError,
} from "../grpc-client/grpcAdapter";
import {
  CreateBrandWarehouseParams,
  UpdateBrandWarehouseParams,
  PublishActivityOfBParams,
} from "../service/declareTypes";
import DataSource from "../bg-enums/dataSource";
import DeliveryMode from "../bg-enums/deliveryMode";
import StorageMode from "../bg-enums/storageMode";

enum GrpcCodeOfInventory {
  InvalidArgument = 3,
  FailedPrecondition = 9,
  Internal = 13,
  Unauthenticated = 16,
}

export interface InventoryWarehouse {
  // 仓库ID（新建时传0）
  id: string;

  // 仓库名称
  name: string;

  // 门店ID(0~总部仓)
  store_id: number;

  // 仓库地址
  address: string;

  // 是否支持自提
  pick_up: boolean;

  // 是否支持同城配送
  city_express: boolean;

  // 是否支持普通快递
  ordinary_express: boolean;

  // 纬度
  latitude: string;

  // 经度
  longitude: string;

  // 城市编码
  city_code: number;

  // 区域编码
  // regionCode: string;

  // 仓库联系人名称（退货使用）
  contact: string;

  // 仓库联系人电话（退货使用）
  mobile: string;

  // 自提模式每日截止下单时间（截止时间后下单则后一个自然日才能自提）
  deadline: string;

  // 库存管理模式，0~弱管控，1~强管控
  storage_mode: number;

  // 模式~总部/门店ID
  p_store_id: string;

  // 使用权ID
  permission_id: number;

  // source, ""~默认，其他~对应系统来源，不落地，对应系统自己记录，作为消息通知返回以便外部依赖使用
  source: string;
}

const getInventoryMetadata = (webposToken: string) => {
  return getMetadata({ token: webposToken, token_type: "web" });
};

interface UsingDefaultValuesOfInventoryWarehouse {
  origin: DataSource;
  cityCode: string;
  deadline: string;
  storeId: string;
  pStoreId: string;
  permissionId: string;
  storageMode: StorageMode;
  pickUp: boolean;
  cityExpress: boolean;
  ordinaryExpress: boolean;
  source: BackendServices;
}

const getDefaultValueOfWarehouse = (
  deliveryModes: DeliveryMode[]
): UsingDefaultValuesOfInventoryWarehouse => {
  const origin = DataSource.LOCAL;
  const cityCode = "156330100"; //暂时用杭州的城市码
  const deadline = "23:59:00";
  const storeId = "0";
  const pStoreId = "0";
  const permissionId = "0";
  const storageMode = StorageMode.WEAK_CONTROL;
  const pickUp = !!deliveryModes.find((v) => v === DeliveryMode.SELF_PICKUP);
  const cityExpress = !!deliveryModes.find((v) => v === DeliveryMode.IN_CITY);
  const ordinaryExpress = !!deliveryModes.find(
    (v) => v === DeliveryMode.EXPRESS
  );

  return {
    origin,
    cityCode,
    deadline,
    storeId,
    pStoreId,
    permissionId,
    storageMode,
    pickUp,
    cityExpress,
    ordinaryExpress,
    source: BackendServices.BGAPI,
  };
};

export interface MakeBrandWarehouseSyncRemoteDataParams {
  remotePK: string;
  name: string;
  address: string;
  deliveryModes: DeliveryMode[];
  lat: string;
  lng: string;
  linkman: string;
  tel: string;
}

export const makeBrandWarehouseSyncRemoteData = ({
  remotePK,
  name,
  address,
  deliveryModes,
  lat,
  lng,
  linkman,
  tel,
}: MakeBrandWarehouseSyncRemoteDataParams) => {
  const {
    cityCode,
    deadline,
    storeId,
    pStoreId,
    permissionId,
    storageMode,
    pickUp,
    cityExpress,
    ordinaryExpress,
    source,
  } = getDefaultValueOfWarehouse(deliveryModes);

  return {
    id: Number(remotePK!),
    name,
    store_id: Number(storeId),
    address,
    pick_up: pickUp,
    city_express: cityExpress,
    ordinary_express: ordinaryExpress,
    latitude: Number(lat),
    longitude: Number(lng),
    city_code: Number(cityCode),
    contact: linkman,
    mobile: tel,
    deadline,
    storage_mode: storageMode,
    p_store_id: pStoreId,
    permission_id: permissionId,
    source,
  };
};

export interface AddInventoryWarehouseParams {
  // 品牌id
  brandId: string;
  // 仓库名称
  name: string;

  // 仓库地址
  address: string;

  deliveryModes: DeliveryMode[];

  // 纬度
  lat: string;

  // 经度
  lng: string;

  // 仓库联系人名称（退货使用）
  linkman: string;

  // 仓库联系人电话（退货使用）
  tel: string;

  remotePK?: string;
}

export const makeCreateBrandWarehouseParams = ({
  brandId,
  name,
  address,
  lat,
  lng,
  linkman,
  tel,
  deliveryModes,
  remotePK,
}: AddInventoryWarehouseParams): CreateBrandWarehouseParams => {
  // const origin = DataSource.LOCAL;
  // const cityCode = "156330100"; //暂时用杭州的城市码
  // const deadline = "23:59:00";
  // const storeId = "0";
  // const pStoreId = "0";
  // const permissionId = "0";
  // const storageMode = StorageMode.WEAK_CONTROL;
  // const deliveryModes: DeliveryMode[] = [DeliveryMode.EXPRESS];
  // const pickUp = !!deliveryModes.find((v) => v === DeliveryMode.SELF_PICKUP);
  // const cityExpress = !!deliveryModes.find((v) => v === DeliveryMode.IN_CITY);
  // const ordinaryExpress = !!deliveryModes.find(
  //   (v) => v === DeliveryMode.EXPRESS
  // );
  // const sourceType = origin === DataSource.LOCAL ? 1 : 0;

  const {
    origin,
    cityCode,
    deadline,
    storeId,
    pStoreId,
    permissionId,
    storageMode,
    // pickUp,
    // cityExpress,
    // ordinaryExpress,
    // source,
  } = getDefaultValueOfWarehouse(deliveryModes);

  const remoteData = makeBrandWarehouseSyncRemoteData({
    remotePK: remotePK!,
    name,
    address,
    deliveryModes,
    lat,
    lng,
    linkman,
    tel,
  });

  const v: CreateBrandWarehouseParams = {
    brandId,
    name,
    tel,
    linkman,
    address,
    lng,
    lat,
    deliveryModes,
    // cityCode,
    // deadline,
    // storageMode,
    // storeId,
    // pStoreId,
    // permissionId,
  };

  return v;
};

export const addInventoryWarehouse = (webposToken: string) => async ({
  brandId,
  name,
  address,
  deliveryModes,
  lat,
  lng,
  linkman,
  tel,
}: AddInventoryWarehouseParams): Promise<CreateBrandWarehouseParams> => {
  console.log("in");
  const cl = getInventoryProxySafely();
  console.log("in2");
  const req = new inventorypb.AddWarehouseRequest();

  const p: CreateBrandWarehouseParams = makeCreateBrandWarehouseParams({
    brandId,
    name,
    address,
    deliveryModes,
    lat,
    lng,
    linkman,
    tel,
  });

  req.setId(0);
  req.setName(name);
  // req.setStoreId(Number(p.storeId));
  req.setAddress(address);
  req.setLatitude(Number(lat));
  req.setLongitude(Number(lng));
  // req.setCityCode(Number(p.cityCode));
  req.setContact(linkman);
  req.setMobile(tel);
  // req.setDeadline(p.deadline);
  // req.setStorageMode(p.storageMode);
  // req.setPStoreId(Number(p.pStoreId));
  // req.setPermissionId(Number(p.permissionId));

  console.log("req set finished");

  return new Promise((resolve, reject) => {
    cl.addWarehouse(
      req,
      getInventoryMetadata(webposToken),
      getOptionsOfLight(),
      (err, res) => {
        if (!isNull(err)) {
          console.log("err=>", err);
          reject(wrapperGrpcError(`${err.details},${err.code}`));
          return;
        }
        // if (!res.getMessage()) {
        //   reject(wrapperGrpcError(res.getMessage()));
        //   return;
        // }
        resolve(p);
      }
    );
  });
};

export const makeUpdateBrandWarehouseParams = ({
  remotePK,
  name,
  address,
  deliveryModes,
  lat,
  lng,
  linkman,
  tel,
}: EditInventoryWarehouseParams): UpdateBrandWarehouseParams => {
  const {
    origin,
    cityCode,
    deadline,
    storeId,
    pStoreId,
    permissionId,
    storageMode,
  } = getDefaultValueOfWarehouse(deliveryModes);

  const remoteData = makeBrandWarehouseSyncRemoteData({
    remotePK,
    name,
    address,
    deliveryModes,
    lat,
    lng,
    linkman,
    tel,
  });

  const v: UpdateBrandWarehouseParams = {
    brandWarehouseId: "",
    // origin,
    name,
    tel,
    linkman,
    address,
    lng,
    lat,
    deliveryModes,
    // cityCode,
    // deadline,
    // storageMode,
    // storeId,
    // pStoreId,
    // permissionId,
    // remotePK: remotePK!,
  };

  return v;
};

export interface EditInventoryWarehouseParams {
  remotePK: string;

  // 仓库名称
  name: string;

  // 仓库地址
  address: string;

  deliveryModes: DeliveryMode[];

  // 纬度
  lat: string;

  // 经度
  lng: string;

  // 仓库联系人名称（退货使用）
  linkman: string;

  // 仓库联系人电话（退货使用）
  tel: string;
}

export const editInventoryWarehouse = (webposToken: string) => async ({
  remotePK,
  name,
  address,
  deliveryModes,
  lat,
  lng,
  linkman,
  tel,
}: EditInventoryWarehouseParams): Promise<UpdateBrandWarehouseParams> => {
  const cl = getInventoryProxySafely();
  const req = new inventorypb.EditWarehouseRequest();

  const p: UpdateBrandWarehouseParams = makeUpdateBrandWarehouseParams({
    remotePK,
    name,
    address,
    deliveryModes,
    lat,
    lng,
    linkman,
    tel,
  });

  req.setId(Number(remotePK));
  req.setName(name);
  // req.setStoreId(Number(p.storeId));
  req.setAddress(address);
  req.setLatitude(Number(lat));
  req.setLongitude(Number(lng));
  // req.setCityCode(Number(p.cityCode));
  req.setContact(linkman);
  req.setMobile(tel);
  // req.setDeadline(p.deadline);
  // req.setStorageMode(p.storageMode);
  // req.setPStoreId(Number(p.pStoreId));

  return new Promise((resolve, reject) => {
    cl.editWarehouse(
      req,
      getInventoryMetadata(webposToken),
      getOptionsOfLight(),
      (err, res) => {
        if (!isNull(err)) {
          console.log("err=>", err);
          reject(wrapperGrpcError(`${err.details},${err.code}`));
          return;
        }
        resolve(p);
      }
    );
  });
};


/*
enum FreezeOrderSource {
  // 1~餐饮pos(外部订单号为pos单号)，2~商城履约订单(外部订单号为商城单号)，3~星团履约订单（外部订单号为星团单号），4~星团活动库存（外部订单号为活动号
  K = 3,
  B = 4,
}

enum StorageType {
  // 仓储类型 2~商品，3~加料
  GOODS = 2,
  FEED = 3,
}

export interface FreezeOrderOfBForActivityDetailParams {
  warehouseRemotePk: string;
  storageKey: string;
  quantity: number;
  storageName: string;
}

export interface CreateFreezeOrderOfBForActivityParams {
  // 品牌mappingId
  brandRemotePk: string;

  // 活动Id
  activityId: string;

  // 活动截止时间戳
  activityEnded: number;

  // 备注 json化对象
  remark: string;

  //订单生成字串(无会员ID时必传，参与单号生成，允许非int，不能超过10位)
  orderKey: string; // 防并发,用userId

  details: FreezeOrderOfBForActivityDetailParams[];
}

export interface CreateFreezeOrderOfBForActivityRet {
  storageKey: string;
  inventoryFreezeNo: string;
}

const genOrderKey = () => {
  return "BG" + randomString(8);
};

export const createFreezeOrderForActivity = (webposToken: string) => async ({
  brandRemotePk,
  activityId,
  activityEnded,
  remark,
  details,
}: CreateFreezeOrderOfBForActivityParams): Promise<PublishActivityOfBParams> => {
  const cl = getInventoryProxySafely();
  const req = new inventorypb.CreateFreezeOrderRequest();

  req.setSgId(Number(brandRemotePk));
  req.setRequestNum(activityId);
  req.setSource(FreezeOrderSource.B); // source==FreezeOrderSource.B, 则requestNum必须传活动id
  // req.setRemark(remark);
  req.setExpireTime(dateFormat(new Date(activityEnded), "yyyy-MM-dd HH:mm:ss"));
  req.setOrderKey(genOrderKey());
  const detailsList = details.map((d) => {
    const pb = new inventorypb.CreateFreezeOrderDetail();
    pb.setId(Number(d.warehouseRemotePk));
    pb.setStorageType(StorageType.GOODS);
    pb.setStorageKey(d.storageKey);
    pb.setQuantity(d.quantity);
    pb.setStorageName(d.storageName);
    pb.setWeightRef(0);
    return pb;
  });
  console.log("detailsList=>", detailsList.length);
  req.setDetailsList(detailsList);

  return new Promise((resolve, reject) => {
    return cl.createFreezeOrder(
      req,
      getInventoryMetadata(webposToken),
      getOptionsOfLight(),
      (err, res) => {
        if (!isNull(err)) {
          console.log("err=>", err);
          reject(wrapperGrpcError(`${err.details},${err.code}`));
          return;
        }
        const p: PublishActivityOfBParams = {
          activityId,
          // inventoryFreezeNo: res.getOrderNumber(),
          userId: "",
        };
        resolve(p);
      }
    );
  });
};

export interface UpdateFreezeOrderOfBForActivityParams {
  // 冻结单号
  orderNumber: string;

  // 请求num
  activityId: string;

  // 活动截止时间戳
  activityEnded: number;

  details: FreezeOrderOfBForActivityDetailParams[];
}

export const updateFreezeOrderForActivity = (webposToken: string) => async ({
  orderNumber,
  activityId,
  activityEnded,
  details,
}: UpdateFreezeOrderOfBForActivityParams): Promise<boolean> => {
  const cl = getInventoryProxySafely();
  const req = new inventorypb.UpdateFreezeOrderRequest();

  req.setOrderNumber(orderNumber);
  req.setRequestNum(activityId);
  req.setSource(FreezeOrderSource.B); // source==FreezeOrderSource.B, 则requestNum必须传活动id
  req.setExpireTime(dateFormat(new Date(activityEnded), "yyyy-MM-dd HH:mm:ss"));
  req.setDetailsList(
    details.map((d) => {
      const pb = new inventorypb.CreateFreezeOrderDetail();
      pb.setId(Number(d.warehouseRemotePk));
      pb.setStorageType(StorageType.GOODS);
      pb.setStorageKey(d.storageKey);
      pb.setQuantity(d.quantity);
      pb.setStorageName(d.storageName);
      pb.setWeightRef(0);
      return pb;
    })
  );

  return new Promise((resolve, reject) => {
    return cl.updateFreezeOrder(
      req,
      getInventoryMetadata(webposToken),
      getOptionsOfLight(),
      (err, res) => {
        if (!isNull(err)) {
          console.log("err=>", err);
          reject(wrapperGrpcError(`${err.details},${err.code}`));
          return;
        }
        resolve(true);
      }
    );
  });
};

export interface EndFreezeOrderOfBForActivityParams {
  // 冻结单号
  orderNumber: string;

  // 请求num
  activityId: string;
}

export const endFreezeOrderForActivity = (webposToken: string) => async ({
  orderNumber,
  activityId,
}: EndFreezeOrderOfBForActivityParams): Promise<boolean> => {
  const cl = getInventoryProxySafely();
  const req = new inventorypb.EndFreezeOrderRequest();

  req.setOrderNumber(orderNumber);
  req.setRequestNum(activityId);
  req.setSource(FreezeOrderSource.B); // source==FreezeOrderSource.B, 则requestNum必须传活动id

  return new Promise((resolve, reject) => {
    return cl.endFreezeOrder(
      req,
      getInventoryMetadata(webposToken),
      getOptionsOfLight(),
      (err, res) => {
        if (!isNull(err)) {
          console.log("err=>", err);
          reject(wrapperGrpcError(`${err.details},${err.code}`));
          return;
        }
        resolve(true);
      }
    );
  });
};
*/